# ==============================================================================
#
# amutils.pm
#
# Account maint utility functions
#
# $Id: amtools.pm,v 1.21 2009/11/02 18:17:38 dyoung2 Exp $
#
# Darren Young [darren.young@gsb.uchicago.edu]
#
# ==============================================================================
#
# ChangeLog
#
# $Log: amtools.pm,v $
# Revision 1.21  2009/11/02 18:17:38  dyoung2
#   * Changed homesys for guest guest
#
# Revision 1.20  2009/10/29 21:34:14  dyoung2
#   * Added guest guest (gg) account info
#
# Revision 1.19  2009/08/12 18:51:11  dyoung2
#   * Added guest faculty stuff
#
# Revision 1.18  2009/07/28 20:32:14  dyoung2
#   * Set alumni mail access to be smtp only
#
# Revision 1.17  2008/04/04 21:53:16  dyoung2
#   * Changes for registrar in testing.
#
# Revision 1.16  2007/08/02 19:16:36  dyoung2
#   * Added GCH values for Exchange forwarding
#
# Revision 1.15  2006/12/07 23:56:38  dyoung2
#   * Updated MAILQUOTA for everyone but alumni to 1048576000
#
# Revision 1.14  2006/09/12 20:21:32  dyoung2
# update
#
# Revision 1.13  2006/07/26 23:09:46  dyoung2
#   * Removed homesys for alumni class
#   * Upped class c in the pecking order above s
#
# Revision 1.12  2006/07/14 23:24:02  dyoung2
#   * Added GCH_LDAPCLASS
#
# Revision 1.11  2006/07/13 21:37:05  dyoung2
#   * Changed mailHost for everyone to be gsbims1
#
# Revision 1.10  2005/09/01 21:47:05  dyoung2
#   * Fixed bug where GCH_SKEL was misspelled GCH_SHEL.
#
# Revision 1.9  2005/08/31 11:49:58  dyoung2
#   * Changed over to new GCH_$$ variable format. Makes these easier to spot
#     in other parts of the code. And, since we've made all global variables
#     cased in CAPITAL letters, that fits the style we've implemented everywhere
#     else.
#
# Revision 1.8  2005/08/29 18:23:20  dyoung2
#   * Changed the rest of dif_class to be _difClass
#
# Revision 1.7  2005/08/29 17:02:29  dyoung2
#   * Disabled %GROUPSIDS in _setHashes.
#
# Revision 1.6  2005/08/29 16:25:24  dyoung2
#   * Changed _validateRecVals to only check if the old class and the new class
#     are exactly the same in the CHG request processing. It previously checked
#     if the old highclass and the new highclass were the same.
#
# Revision 1.5  2005/08/25 22:38:04  dyoung2
#   * Added "*" as the very first class to allow it to be passed in.
#
# Revision 1.4  2005/08/25 18:16:01  dyoung2
#   * Changed fac dir location
#
# Revision 1.3  2005/06/27 16:30:19  dyoung2
#   * Removed some fixme messages.
#
# Revision 1.2  2005/06/14 17:52:22  dyoung2
#   * Added _setHashes().
#
# Revision 1.1  2005/06/03 01:45:24  dyoung2
#   * Renamed from amutils.pm
#
# Revision 1.2  2005/06/03 01:42:01  dyoung2
#   * Merged in functions from acctclass.pm.
#
# Revision 1.1  2005/05/31 20:51:41  dyoung2
#   * Initial version.
#   * Added _validateRecVals() function.
#
# ==============================================================================

my  $cvsid   = '$Id: amtools.pm,v 1.21 2009/11/02 18:17:38 dyoung2 Exp $';
my  @cvsinfo = split( ' ', $cvsid );
our $NAME    = File::Basename::basename($0);
our $VERSION = $cvsinfo[2];

# ------------------------------------------------------------------------------
#                             B E G I N
# ------------------------------------------------------------------------------
BEGIN {

    # Pragmas
    use strict;

    # "Standard" modules we use
    use FindBin;
    use Config::Simple;
    use lib "$FindBin::Bin/../lib";

    # Standard account maint modules to use
    use logging;
    use errcodes;
    use utils;
    
    # Modules that this module uses
    use dbtools;
    use adtools;
    use unixtools;

}


# ------------------------------------------------------------------------------ 
#                             V A R I A B L E S
# ------------------------------------------------------------------------------ 
our $LOGFILE    = "$FindBin::Bin/../log/acctmgr.log" unless($LOGFILE); 
our $CONFIGFILE = "$FindBin::Bin/../etc/acctmgr.cfg" unless($CONFIGFILE); 


# ------------------------------------------------------------------------------
#                             C O N F I G   F I L E
# ------------------------------------------------------------------------------
our $CFG = new Config::Simple( filename => $CONFIGFILE ) or die "$!\n" unless($CFG);


# =============================================================================
# NAME        : _validateRecVals
# DESCRIPTION : validate a given account maint record 
# REQUIRES    : string(reqtype), string(record)
# RETURNS     : TRUE or FALSE
# NOTES       : You have to determine the type BEFORE calling this
# =============================================================================
sub _validateRecVals {
    my $name = "_validateRecVals()";
    my ( $package, $filename, $line ) = caller;
    debug("$name: entering with args @_");
    debug("$name: called from package->$package, filename->$filename, line->$line");

    my ( $type, $recin ) = @_;

    #### MAP OF REQUIRED AND UNUSED DATA FIELDS ####
    #
    # FIELD DEFINITIONS:
    #   0 - Username 
    #   1 - Person ID
    #   2 - Encrypted Password
    #   3 - Full Name
    #   4 - Last Name
    #   5 - First Name
    #   6 - Plaintext Password
    #   7 - Old Class
    #   8 - New Class
    #
    # FIELD REQUIREMENTS:
    # ------------------------------------------
    # type | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    # ------------------------------------------
    #  add | R | U | R | R | R | R | R | U | R |
    #  chg | R | U | U | U | U | U | U | R | R |
    #  del | R | U | U | U | U | U | U | R | U |
    #  pwd | R | U | R | U | U | U | R | U | U |
    # ------------------------------------------

    my @recfields = split( /\:/, $recin, 9 );
    my $retval    = 1;
    my $ctr       = 0;
    my $error     = 0;
    my @fields    = ();

    # field names
    my $username  = $recfields[0];
    my $personid  = $recfields[1];
    my $encpass   = $recfields[2];
    my $fullname  = $recfields[3];
    my $lastname  = $recfields[4];
    my $firstname = $recfields[5];
    my $plainpass = $recfields[6];
    my $oldclass  = $recfields[7];
    my $newclass  = $recfields[8];


    # Field descriptions (used for error messages)
    $fields[0] = "Username";
    $fields[1] = "Person ID";
    $fields[2] = "Encrypted Password";
    $fields[3] = "Full Name";
    $fields[4] = "Last Name";
    $fields[5] = "First Name";
    $fields[6] = "Plaintext Password";
    $fields[7] = "Old Class";
    $fields[8] = "New Class";

    # R = Required field
    # U = Unused field
    my @add    = ( 'R', 'U', 'R', 'R', 'R', 'R', 'R', 'U', 'R' );
    my @chg    = ( 'R', 'U', 'U', 'U', 'U', 'U', 'U', 'R', 'R' );
    my @del    = ( 'R', 'U', 'U', 'U', 'U', 'U', 'U', 'R', 'U' );
    my @pwd    = ( 'R', 'U', 'R', 'U', 'U', 'U', 'R', 'U', 'U' );

    debug("$name: checking record type -> $type");

    ### Verify that the correct number of fields are present for the 
    ### given record type. do this BEFORE we start the in-depth validation
    for ( $ctr = 0; $ctr < scalar(@recin); $ctr++ ) {

        # used for display purposes ONLY
        if ( $fields[$ctr] =~ /password/i ) {
            $val = "** HIDDEN **";      # hide the password fields
        } elsif ( $recfields[$ctr] eq "" ) {
            $val = "** NULL **";        # better than just "" in the log file...
        } else { 
            $val = $recfields[$ctr];    # otherwise the value we were given 
        }
        debug("$name: checking field -> $ctr");
        debug("$name:   descr  -> $fields[$ctr]");
        debug("$name:   val    -> $val");

        ### Check add records ###
        if ( $type eq "add" ) {
            if ( ( $add[$ctr] eq 'R' ) && ( ! $recfields[$ctr] ) ) {
                debug("$name: record missing field #$ctr: ($fields[$ctr])");
                $retval = 0;
            }

        ### Check chg records ###
        } elsif ( $type eq "chg" ) {
            if ( ( $chg[$ctr] eq 'R' ) && ( ! $recfields[$ctr] ) ) {
                debug("$name: record missing field #$ctr: ($fields[$ctr])");
                $retval = 0;
            }

        ### Check del records ###
        } elsif ( $type eq "del" ) {
            if ( ( $del[$ctr] eq /'R'/ ) && ( ! $recfields[$ctr] ) ) {
                debug("$name: record missing field #$ctr: ($fields[$ctr])");
                $retval = 0;
            }

        ### Check pwd records ###
        } elsif ( $type eq "pwd" ) {
            if ( ( $pwd[$ctr] eq /'R'/ ) && ( ! $recfields[$ctr] ) ) {
                debug("$name: record missing field #$ctr: ($fields[$ctr])");
                $retval = 0;
            }
        }

    } ### end for() loop

    ### If we've blown up somewhere before here, return with false
    unless ( $retval ) {
        debug("$name: returning with retval $retval");
        return($retval);
    }


    ### Since the basic field existence tests passed, perform extended
    ### checks on the individual record types
    SWITCH: for ( $type ) {

        ### ------------ ###
        ### ADD REQUESTS ###
        ### ------------ ###
        /add/   && do {
                };


        ### ------------ ###
        ### CHG REQUESTS ###
        ### ------------ ###
        /chg/   && do {
                    ### make sure the high class for both the old and the new class
                    ### are different. if they're the same, then this really isn't a
                    ### change now is it?
                    if ( $oldclass eq $newclass ) {
                        debug("$name: ** FAILED ** Old class and new class are the same");
                        $retval = 0;
                    }
                };


        ### ------------ ###
        ### DEL REQUESTS ###
        ### ------------ ###
        /del/   && do {
                };


        ### ------------ ###
        ### PWD REQUESTS ###
        ### ------------ ###
        /pwd/   && do {
                };

    }

    debug("$name: returning with retval $retval");
    return($retval);

}


# =============================================================================
# NAME        : _getHighClass
# DESCRIPTION : take a string of classes and determines the "highest" one
# REQUIRES    : string(class)
# RETURNS     : string(class)
# NOTES       : inclass must be in the form of (class,class)
# =============================================================================
sub _getHighClass {
    my ($inclass) = @_;   
    my $name = "_getHighClass()";
    my ( $package, $filename, $line ) = caller; 
    debug("$name: entering with args @_");
    debug("$name: called from package->$package, filename->$filename, line->$line");

    if ( ! defined($inclass)) {
        logmsg("$name: SYNTAX ERROR (must give me a class to test)");
        return(0);
    }

    my @classes     = split( ',', $inclass );
    my $highclass   = -1;
    my @acctclasses = ( "*", "l", "n", "r", "a", "ts", "s", "c", "tm", "m", "p", "gg", "gf", "f" );
    my $i;
    my $ctr; 
    my %classrank;

    for ( $ctr = 0; $ctr < @acctclasses; $ctr++ ) {
        $classrank{$acctclasses[$ctr]} = $ctr;
        debug("$name: $acctclasses[$ctr] = $ctr");
    }

    for ( $i = 0; $i < @classes; $i++ ) {
        if ( defined $classrank{ $classes[$i] } ) {
            if ( $classrank{ $classes[$i] } > $highclass ) {
                debug("$name: $classrank{$classes[$i]} > $highclass");
                $highclass = $classrank{ $classes[$i] };
            }
        } else {
            debug("$name: bad account class: $classes[$i]");
            return undef;
        }       
    }

    debug("$name: returning with val " . $acctclasses[$highclass]);
    return($acctclasses[$highclass]);
}


# =============================================================================
# NAME        : _difClass
# DESCRIPTION : 
# REQUIRES    : 
# RETURNS     : 
# NOTES       : 
# =============================================================================
sub _difClass { 
    my (@class0, $class1) = @_; 
    my $name = "_difClass()"; 
    my ( $package, $filename, $line ) = caller;  
    debug("$name: entering with args @_"); 
    debug("$name: called from package->$package, filename->$filename, line->$line"); 

    my $cl;
    my $class;
 
    $class  = ""; 
    $class1 = ",$_[1],"; 
    @class0 = reverse( split( ',', $_[0] ) ); 

    debug("$name: class  => $class");
    debug("$name: class1 => $class1");
    debug("$name: class0 array length => " . scalar(@class0));
 
    foreach $cl (@class0) { 
        $class .= "$cl," unless ( $class1 =~ /\,$cl\,/ ); 
    } 

    if ( $class ne "" ) { 
        chop $class;    # chop trailing ',' 
    } 

    debug("$name: returning with val $class");
    return ($class); 
} 


# =============================================================================
# NAME        :
# DESCRIPTION :
# REQUIRES    :
# RETURNS     :
# NOTES       : 
# =============================================================================
sub _setHashes {
    my $name = "_setHashes";
    my ( $package, $filename, $line ) = caller; 
    debug("$name: entering with args @_");
    debug("$name: called from package->$package, filename->$filename, line->$line");      

    ### Applicants
    $GCH_LDAPTP{"l"}     = "";
    $GCH_OUTP{"l"}       = "";
    $GCH_LDAPGRP{"l"}    = "";
    $GCH_GID{"l"}        = _getGroupIdByName("applicnt");
    $GCH_SHELL{"l"}      = "/dev/null";
    $GCH_NETGRP{"l"}     = "";
    $GCH_HOMESYS{"l"}    = "gsbmba";
    $GCH_AWAYSYS{"l"}    = "";
    $GCH_HOMEDISK{"l"}   = "/export/home";
    $GCH_SKEL{"l"}       = "mba";
    $GCH_ALIASGRP{"l"}   = "applicants";
    $GCH_MMLISTS{"l"}    = "";
    $GCH_MAILHOST{'l'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'l'}  = "primary";
    $GCH_MAILQUOTA{'l'}  = "1048576000";
    $GCH_LDAPCLASS{'l'}  = "applicnt";
    $GCH_MAILACCESS{'l'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### New Admits
    $GCH_LDAPTP{"n"}     = "Newly Admitted Student";
    $GCH_OUTP{"n"}       = "New Admits";
    $GCH_LDAPGRP{"n"}    = "newadmits";
    $GCH_GID{"n"}        = _getGroupIdByName("newadmit");
    $GCH_SHELL{"n"}      = "/dev/null";
    $GCH_NETGRP{"n"}     = "";
    $GCH_HOMESYS{"n"}    = "gsbmba";
    $GCH_AWAYSYS{"n"}    = "";
    $GCH_HOMEDISK{"n"}   = "/export/home";
    $GCH_SKEL{"n"}       = "mba";
    $GCH_ALIASGRP{"n"}   = "";
    $GCH_MMLISTS{"n"}    = "";
    $GCH_MAILHOST{'n'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'n'}  = "primary";
    $GCH_MAILQUOTA{'n'}  = "1048576000";
    $GCH_LDAPCLASS{'n'}  = "newadmit";
    $GCH_MAILACCESS{'n'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';
    
    ### Faculty RA
    $GCH_LDAPTP{"r"}     = "RA for Faculty";
    $GCH_OUTP{"r"}       = "GSB";
    $GCH_LDAPGRP{"r"}    = "";
    $GCH_GID{"r"}        = _getGroupIdByName("students");
    $GCH_SHELL{"r"}      = "/bin/bash";
    $GCH_NETGRP{"r"}     = "ra";
    $GCH_HOMESYS{"r"}    = "gsbfac";
    $GCH_AWAYSYS{"r"}    = "";
    $GCH_HOMEDISK{"r"}   = "/export/home";
    $GCH_SKEL{"r"}       = "fac";
    $GCH_ALIASGRP{"r"}   = "research-assistants";
    $GCH_MMLISTS{"r"}    = "";
    $GCH_MAILHOST{'r'}   = "gsbims1.uchicago.edu";    
    $GCH_MAILSTORE{'r'}  = "primary";
    $GCH_MAILQUOTA{'r'}  = "1048576000";
    $GCH_LDAPCLASS{'r'}  = "students";
    $GCH_MAILACCESS{'r'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';
    
    ### Staff - Computing Services
    $GCH_LDAPTP{"c"}     = "Staff";
    $GCH_OUTP{"c"}       = "GSB";
    $GCH_LDAPGRP{"c"}    = "Staff";
    $GCH_GID{"c"}        = _getGroupIdByName("cs");
    $GCH_SHELL{"c"}      = "/bin/bash";
    $GCH_NETGRP{"c"}     = "cs";
    $GCH_HOMESYS{"c"}    = "gsbmba";
    $GCH_AWAYSYS{"c"}    = "";
    $GCH_HOMEDISK{"c"}   = "/export/home";
    $GCH_SKEL{"c"}       = "cs";
    $GCH_ALIASGRP{"c"}   = "computing-services";
    $GCH_MMLISTS{"c"}    = "";
    $GCH_MAILHOST{'c'}   = "gsbims1.uchicago.edu";    
    $GCH_MAILSTORE{'c'}  = "primary";
    $GCH_MAILQUOTA{'c'}  = "1048576000";
    $GCH_LDAPCLASS{'c'}  = "cs";
    $GCH_MAILACCESS{'c'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';
    
    ### Alumni
    $GCH_LDAPTP{"a"}     = "Alumni";
    $GCH_OUTP{"a"}       = "GSB Alumni";
    $GCH_LDAPGRP{"a"}    = "";
    $GCH_GID{"a"}        = _getGroupIdByName("alumni");
    $GCH_SHELL{"a"}      = "/dev/null";
    $GCH_NETGRP{"a"}     = "";
    $GCH_HOMESYS{"a"}    = "";
    $GCH_AWAYSYS{"a"}    = "";
    $GCH_HOMEDISK{"a"}   = "";
    $GCH_SKEL{"a"}       = "";
    $GCH_ALIASGRP{"a"}   = "";
    $GCH_MMLISTS{"a"}    = "";
    $GCH_MAILHOST{'a'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'a'}  = "primary";
    $GCH_MAILQUOTA{'a'}  = "20971520";
    $GCH_LDAPCLASS{'a'}  = "alumni";
    $GCH_MAILACCESS{'a'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### Staff - Temporary
    $GCH_LDAPTP{"ts"}     = "Temporary GSB Person";
    $GCH_OUTP{"ts"}       = "GSB";
    $GCH_LDAPGRP{"ts"}    = "Staff";
    $GCH_GID{"ts"}        = _getGroupIdByName("staff");
    $GCH_SHELL{"ts"}      = "/bin/bash";
    $GCH_NETGRP{"ts"}     = "staff";
    $GCH_HOMESYS{"ts"}    = "gsbmba";
    $GCH_AWAYSYS{"ts"}    = "";
    $GCH_HOMEDISK{"ts"}   = "/export/home";
    $GCH_SKEL{"ts"}       = "stf";
    $GCH_ALIASGRP{"ts"}   = "staff";
    $GCH_MMLISTS{"ts"}    = "staff2003";
    $GCH_MAILHOST{'ts'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'ts'}  = "primary";
    $GCH_MAILQUOTA{'ts'}  = "1048576000";
    $GCH_LDAPCLASS{'ts'}  = "staff";
    $GCH_MAILACCESS{'ts'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### Staff
    $GCH_LDAPTP{"s"}     = "Staff";
    $GCH_OUTP{"s"}       = "GSB";
    $GCH_LDAPGRP{"s"}    = "Staff";
    $GCH_GID{"s"}        = _getGroupIdByName("staff");
    $GCH_SHELL{"s"}      = "/bin/bash";
    $GCH_NETGRP{"s"}     = "staff";
    $GCH_HOMESYS{"s"}    = "gsbmba";
    $GCH_AWAYSYS{"s"}    = "";
    $GCH_HOMEDISK{"s"}   = "/export/home";
    $GCH_SKEL{"s"}       = "stf";
    $GCH_ALIASGRP{"s"}   = "staff";
    $GCH_MMLISTS{"s"}    = "staff2003";
    $GCH_MAILHOST{'s'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'s'}  = "primary";
    $GCH_MAILQUOTA{'s'}  = "1048576000";
    $GCH_LDAPCLASS{'s'}  = "staff";
    $GCH_MAILACCESS{'s'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### MBA - Temporary (as in GSAL)
    $GCH_LDAPTP{"tm"}     = "Temporary MBA student";
    $GCH_OUTP{"tm"}       = "GSB";
    $GCH_LDAPGRP{"tm"}    = "";
    $GCH_GID{"tm"}        = _getGroupIdByName("mba");
    $GCH_SHELL{"tm"}      = "/bin/bash";
    $GCH_NETGRP{"tm"}     = "mba";
    $GCH_HOMESYS{"tm"}    = "gsbmba";
    $GCH_AWAYSYS{"tm"}    = "";
    $GCH_HOMEDISK{"tm"}   = "/export/home";
    $GCH_SKEL{"tm"}       = "mba";
    $GCH_ALIASGRP{"tm"}   = "";
    $GCH_MMLISTS{"tm"}    = "";
    $GCH_MAILHOST{'tm'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'tm'}  = "primary";
    $GCH_MAILQUOTA{'tm'}  = "1048576000";
    $GCH_LDAPCLASS{'tm'}  = "mba";
    $GCH_MAILACCESS{'tm'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### MBA
    $GCH_LDAPTP{"m"}     = "MBA student";
    $GCH_OUTP{"m"}       = "GSB";
    $GCH_LDAPGRP{"m"}    = "";
    $GCH_GID{"m"}        = _getGroupIdByName("mba");
    $GCH_SHELL{"m"}      = "/bin/bash";
    $GCH_NETGRP{"m"}     = "mba";
    $GCH_HOMESYS{"m"}    = "gsbmba";
    $GCH_AWAYSYS{"m"}    = "";
    $GCH_HOMEDISK{"m"}   = "/export/home";
    $GCH_SKEL{"m"}       = "mba";
    $GCH_ALIASGRP{"m"}   = "";
    $GCH_MMLISTS{"m"}    = "";
    $GCH_MAILHOST{'m'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'m'}  = "primary";
    $GCH_MAILQUOTA{'m'}  = "1048576000";
    $GCH_LDAPCLASS{'m'}  = "mba";
    $GCH_MAILACCESS{'m'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### PHD
    $GCH_LDAPTP{"p"}     = "PhD student";
    $GCH_OUTP{"p"}       = "GSB";
    $GCH_LDAPGRP{"p"}    = "";
    $GCH_GID{"p"}        = _getGroupIdByName("phd");
    $GCH_SHELL{"p"}      = "/bin/bash";
    $GCH_NETGRP{"p"}     = "phd";
    $GCH_HOMESYS{"p"}    = "gsbphd";
    $GCH_AWAYSYS{"p"}    = "";
    $GCH_HOMEDISK{"p"}   = "/export/home";
    $GCH_SKEL{"p"}       = "phd";
    $GCH_ALIASGRP{"p"}   = "phd-students";
    $GCH_MMLISTS{"p"}    = "";
    $GCH_MAILHOST{'p'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'p'}  = "primary";
    $GCH_MAILQUOTA{'p'}  = "1048576000";
    $GCH_LDAPCLASS{'p'}  = "phd";
    $GCH_MAILACCESS{'p'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### Faculty
    $GCH_LDAPTP{"f"}     = "Faculty";
    $GCH_OUTP{"f"}       = "GSB";
    $GCH_LDAPGRP{"f"}    = "Faculty";
    $GCH_GID{"f"}        = _getGroupIdByName("fac");
    $GCH_SHELL{"f"}      = "/bin/bash";
    $GCH_NETGRP{"f"}     = "fac";
    $GCH_HOMESYS{"f"}    = "gsbfac";
    $GCH_AWAYSYS{"f"}    = "";
    $GCH_HOMEDISK{"f"}   = "/export/home";
    $GCH_SKEL{"f"}       = "fac";
    $GCH_ALIASGRP{"f"}   = "faculty";
    $GCH_MMLISTS{"f"}    = "";
    $GCH_MAILHOST{'f'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'f'}  = "primary";
    $GCH_MAILQUOTA{'f'}  = "1048576000";
    $GCH_LDAPCLASS{'f'}  = "fac";
    $GCH_MAILACCESS{'f'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### Guest Faculty
    $GCH_LDAPTP{"gf"}     = "Guest Faculty";
    $GCH_OUTP{"gf"}       = "GSB";
    $GCH_LDAPGRP{"gf"}    = "Guest Faculty";
    $GCH_GID{"gf"}        = _getGroupIdByName("gstfac");
    $GCH_SHELL{"gf"}      = "/bin/bash";
    $GCH_NETGRP{"gf"}     = "gstfac";
    $GCH_HOMESYS{"gf"}    = "gsbfac";
    $GCH_AWAYSYS{"gf"}    = "";
    $GCH_HOMEDISK{"gf"}   = "";
    $GCH_SKEL{"gf"}       = "fac";
    $GCH_ALIASGRP{"gf"}   = "faculty";
    $GCH_MMLISTS{"gf"}    = "";
    $GCH_MAILHOST{'gf'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'gf'}  = "primary";
    $GCH_MAILQUOTA{'gf'}  = "1048576000";
    $GCH_LDAPCLASS{'gf'}  = "gstfac";
    $GCH_MAILACCESS{'gf'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    ### Guest Guest
    $GCH_LDAPTP{"gg"}     = "Guest Guest";
    $GCH_OUTP{"gg"}       = "GSB";
    $GCH_LDAPGRP{"gg"}    = "Guest Guest";
    $GCH_GID{"gg"}        = _getGroupIdByName("gstgst");
    $GCH_SHELL{"gg"}      = "/bin/bash";
    $GCH_NETGRP{"gg"}     = "gstgst";
    $GCH_HOMESYS{"gg"}    = "gsbfac";
    $GCH_AWAYSYS{"gg"}    = "";
    $GCH_HOMEDISK{"gg"}   = "";
    $GCH_SKEL{"gg"}       = "fac";
    $GCH_ALIASGRP{"gg"}   = "faculty";
    $GCH_MMLISTS{"gg"}    = "";
    $GCH_MAILHOST{'gg'}   = "gsbims1.uchicago.edu";
    $GCH_MAILSTORE{'gg'}  = "primary";
    $GCH_MAILQUOTA{'gg'}  = "1048576000";
    $GCH_LDAPCLASS{'gg'}  = "gstgst";
    $GCH_MAILACCESS{'gg'} = '-imap:ALL$-imaps:ALL$-pop:ALL$-pops:ALL$-http:ALL';

    debug("$name: returning with val 1");
    return(1);
}

# =============================================================================
# NAME        : _getNextPOSIXid
# DESCRIPTION : Return the next available uid from the password file
# REQUIRES    : Nothing
# RETURNS     : string(uid)
# NOTES       : This is the bastard that started the whole acount maint rewrite
#             : See doc/README for details.
# =============================================================================
sub _getNextPOSIXid {
    my ( $pwfile ) = @_;
    my $name = "_getNextPOSIXid";
    my ( $package, $filename, $line ) = caller;
    logmsg("$name: entering with args @_");
    logmsg("$name: called from package->$package, filename->$filename, line->$line");

    # Use the globally defined password file if we weren't given one
    unless ( defined($pwfile) ) {
        $pwfile = $PASSWDFILE;
        logmsg("$name: using global passwd file: $PASSWDFILE");
    }

    my $pwentry   = "";
    my %CURNISIDS = ();
    my $nextUID   = "";
    my $ctr       = 4999;

    ### open the password file for read ###
    if ( open( PWFILE, "<$pwfile" ) ) {
        debug("$name: successfully opened passwd file $pwfile");
    } else {
        logmsg("$name: ** FATAL ERROR ** Unable to open passwd file $pwfile ($!)");
        exit(SHELL_FALSE);
    }

    while ( chomp( $pwentry = <PWFILE> ) ) {
        my (
             $username,
             $encrypted,
             $uid,
             $gid,
             $gecos,
             $homedir,
             $shell 
           ) = split( /\:/, $pwentry, 7 );

        $CURNISIDS{$uid} = $uid;
    }

    close( PWFILE );

    while ( $ctr < 65535 ) {
        $ctr++;
        if ( exists $CURNISIDS{"$ctr"} ) {
            next;
        } else {
            $nextUID = $ctr;
            last;
        }
    }

    logmsg("$name: got next id of $nextUID");
    ($nextUID) ? return ($nextUID) : return(0);
}
1;
